Proper connect_port
[juce-lv2.git] / juce / source / extras / the jucer / src / ui / jucer_ComponentLayoutEditor.cpp
blob1a49d26aa36eca0b7b43c920b98f31d439e85899
1 /*
2 ==============================================================================
4 This file is part of the JUCE library - "Jules' Utility Class Extensions"
5 Copyright 2004-11 by Raw Material Software Ltd.
7 ------------------------------------------------------------------------------
9 JUCE can be redistributed and/or modified under the terms of the GNU General
10 Public License (Version 2), as published by the Free Software Foundation.
11 A copy of the license is included in the JUCE distribution, or can be found
12 online at www.gnu.org/licenses.
14 JUCE is distributed in the hope that it will be useful, but WITHOUT ANY
15 WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
16 A PARTICULAR PURPOSE. See the GNU General Public License for more details.
18 ------------------------------------------------------------------------------
20 To release a closed-source product which uses JUCE, commercial licenses are
21 available: visit www.rawmaterialsoftware.com/juce for more information.
23 ==============================================================================
26 #include "../jucer_Headers.h"
27 #include "jucer_ComponentLayoutEditor.h"
28 #include "../model/jucer_ObjectTypes.h"
29 #include "../model/components/jucer_JucerComponentHandler.h"
31 //==============================================================================
32 class SubComponentHolderComp : public Component
34 public:
35 SubComponentHolderComp (JucerDocument& document_,
36 SnapGridPainter& grid_)
37 : document (document_),
38 grid (grid_),
39 dontFillBackground (false)
41 setInterceptsMouseClicks (false, false);
42 setWantsKeyboardFocus (false);
43 setFocusContainer (true);
46 ~SubComponentHolderComp()
50 void paint (Graphics& g)
52 if (! dontFillBackground)
54 PaintRoutine* const background = document.getPaintRoutine (0);
56 if (background != 0)
58 background->fillWithBackground (g, false);
59 background->drawElements (g, Rectangle<int> (0, 0, getWidth(), getHeight()));
62 grid.draw (g, background);
66 void resized()
68 if (! getBounds().isEmpty())
70 int numTimesToTry = 10;
72 while (--numTimesToTry >= 0)
74 bool anyCompsMoved = false;
76 for (int i = 0; i < getNumChildComponents(); ++i)
78 Component* comp = getChildComponent (i);
79 ComponentTypeHandler* const type = ComponentTypeHandler::getHandlerFor (*comp);
81 if (type != 0)
83 const Rectangle<int> newBounds (type->getComponentPosition (comp)
84 .getRectangle (Rectangle<int> (0, 0, getWidth(), getHeight()),
85 document.getComponentLayout()));
87 anyCompsMoved = anyCompsMoved || (comp->getBounds() != newBounds);
88 comp->setBounds (newBounds);
92 // repeat this loop until they've all stopped shuffling (might require a few
93 // loops for all the relative positioned comps to settle down)
94 if (! anyCompsMoved)
95 break;
100 void moved()
102 ((ComponentLayoutEditor*) getParentComponent())->updateOverlayPositions();
105 JucerDocument& document;
106 SnapGridPainter& grid;
107 bool dontFillBackground;
110 //==============================================================================
111 ComponentLayoutEditor::ComponentLayoutEditor (JucerDocument& document_, ComponentLayout& layout_)
112 : document (document_),
113 layout (layout_),
114 firstResize (true)
116 setWantsKeyboardFocus (true);
118 addAndMakeVisible (subCompHolder = new SubComponentHolderComp (document, grid));
120 refreshAllComponents();
122 setSize (document.getInitialWidth(), document.getInitialHeight());
125 ComponentLayoutEditor::~ComponentLayoutEditor()
127 document.removeChangeListener (this);
129 removeChildComponent (&lassoComp);
130 deleteAllChildren();
133 //==============================================================================
134 void ComponentLayoutEditor::visibilityChanged()
136 document.getUndoManager().beginNewTransaction();
138 if (isVisible())
140 refreshAllComponents();
141 document.addChangeListener (this);
143 else
145 document.removeChangeListener (this);
149 void ComponentLayoutEditor::changeListenerCallback (ChangeBroadcaster*)
151 refreshAllComponents();
154 void ComponentLayoutEditor::paint (Graphics& g)
158 void ComponentLayoutEditor::resized()
160 if (firstResize && getWidth() > 0 && getHeight() > 0)
162 firstResize = false;
163 refreshAllComponents();
166 subCompHolder->setBounds (getComponentArea());
167 updateOverlayPositions();
170 const Rectangle<int> ComponentLayoutEditor::getComponentArea() const
172 if (document.isFixedSize())
174 return Rectangle<int> ((getWidth() - document.getInitialWidth()) / 2,
175 (getHeight() - document.getInitialHeight()) / 2,
176 document.getInitialWidth(),
177 document.getInitialHeight());
179 else
181 return Rectangle<int> (editorEdgeGap, editorEdgeGap,
182 getWidth() - editorEdgeGap * 2,
183 getHeight() - editorEdgeGap * 2);
187 const Image ComponentLayoutEditor::createComponentLayerSnapshot() const
189 ((SubComponentHolderComp*) subCompHolder)->dontFillBackground = true;
190 Image im = subCompHolder->createComponentSnapshot (Rectangle<int> (0, 0, subCompHolder->getWidth(), subCompHolder->getHeight()));
191 ((SubComponentHolderComp*) subCompHolder)->dontFillBackground = false;
193 return im;
196 void ComponentLayoutEditor::updateOverlayPositions()
198 for (int i = getNumChildComponents(); --i >= 0;)
200 ComponentOverlayComponent* const overlay = dynamic_cast <ComponentOverlayComponent*> (getChildComponent (i));
202 if (overlay != 0)
203 overlay->updateBoundsToMatchTarget();
207 void ComponentLayoutEditor::refreshAllComponents()
209 int i;
210 for (i = getNumChildComponents(); --i >= 0;)
212 ComponentOverlayComponent* const overlay = dynamic_cast <ComponentOverlayComponent*> (getChildComponent (i));
214 if (overlay != 0 && ! layout.containsComponent (overlay->target))
215 delete overlay;
218 for (i = subCompHolder->getNumChildComponents(); --i >= 0;)
220 Component* const comp = subCompHolder->getChildComponent (i);
222 if (! layout.containsComponent (comp))
223 subCompHolder->removeChildComponent (comp);
226 Component* lastComp = 0;
227 Component* lastOverlay = 0;
229 for (i = layout.getNumComponents(); --i >= 0;)
231 Component* const c = layout.getComponent (i);
232 ComponentOverlayComponent* overlay = getOverlayCompFor (c);
234 bool isNewOverlay = false;
236 if (overlay == 0)
238 ComponentTypeHandler* const handler = ComponentTypeHandler::getHandlerFor (*c);
239 jassert (handler != 0);
241 overlay = handler->createOverlayComponent (c, layout);
243 addAndMakeVisible (overlay);
244 isNewOverlay = true;
247 if (lastOverlay != 0)
248 overlay->toBehind (lastOverlay);
249 else
250 overlay->toFront (false);
252 lastOverlay = overlay;
254 subCompHolder->addAndMakeVisible (c);
256 if (lastComp != 0)
257 c->toBehind (lastComp);
258 else
259 c->toFront (false);
261 lastComp = c;
263 c->setWantsKeyboardFocus (false);
264 c->setFocusContainer (true);
266 if (isNewOverlay)
267 overlay->updateBoundsToMatchTarget();
270 if (grid.updateFromDesign (document))
271 subCompHolder->repaint();
273 subCompHolder->setBounds (getComponentArea());
274 subCompHolder->resized();
277 void ComponentLayoutEditor::mouseDown (const MouseEvent& e)
279 if (e.mods.isPopupMenu())
281 PopupMenu m;
283 m.addCommandItem (commandManager, CommandIDs::editCompLayout);
284 m.addCommandItem (commandManager, CommandIDs::editCompGraphics);
285 m.addSeparator();
287 for (int i = 0; i < ObjectTypes::numComponentTypes; ++i)
288 m.addCommandItem (commandManager, CommandIDs::newComponentBase + i);
290 m.show();
292 else
294 addChildComponent (&lassoComp);
295 lassoComp.beginLasso (e, this);
299 void ComponentLayoutEditor::mouseDrag (const MouseEvent& e)
301 lassoComp.toFront (false);
302 lassoComp.dragLasso (e);
305 void ComponentLayoutEditor::mouseUp (const MouseEvent& e)
307 lassoComp.endLasso();
308 removeChildComponent (&lassoComp);
310 if (e.mouseWasClicked() && ! e.mods.isAnyModifierKeyDown())
311 layout.getSelectedSet().deselectAll();
314 static void moveOrStretch (ComponentLayout& layout, int x, int y, bool snap, bool stretch)
316 if (stretch)
317 layout.stretchSelectedComps (x, y, snap);
318 else
319 layout.moveSelectedComps (x, y, snap);
322 bool ComponentLayoutEditor::keyPressed (const KeyPress& key)
324 const bool snap = key.getModifiers().isAltDown();
325 const bool stretch = key.getModifiers().isShiftDown();
327 const int amount = snap ? document.getSnappingGridSize() + 1
328 : 1;
330 if (key.isKeyCode (KeyPress::rightKey))
332 moveOrStretch (layout, amount, 0, snap, stretch);
334 else if (key.isKeyCode (KeyPress::downKey))
336 moveOrStretch (layout, 0,amount, snap, stretch);
338 else if (key.isKeyCode (KeyPress::leftKey))
340 moveOrStretch (layout, -amount, 0, snap, stretch);
342 else if (key.isKeyCode (KeyPress::upKey))
344 moveOrStretch (layout, 0, -amount, snap, stretch);
346 else
348 return false;
351 return true;
354 bool ComponentLayoutEditor::isInterestedInFileDrag (const StringArray& filenames)
356 const File f (filenames [0]);
357 return f.hasFileExtension (".cpp");
360 void ComponentLayoutEditor::filesDropped (const StringArray& filenames, int x, int y)
362 const File f (filenames [0]);
364 if (f.hasFileExtension (".cpp"))
366 JucerDocument* doc = ObjectTypes::loadDocumentFromFile (f, false);
368 if (doc != 0)
370 delete doc;
372 JucerComponentHandler jucerDocHandler;
373 layout.getDocument()->getUndoManager().beginNewTransaction();
375 TestComponent* newOne
376 = dynamic_cast <TestComponent*> (layout.addNewComponent (&jucerDocHandler,
377 x - subCompHolder->getX(),
378 y - subCompHolder->getY()));
380 if (newOne != 0)
382 JucerComponentHandler::setJucerComponentFile (*layout.getDocument(), newOne, f.getRelativePathFrom (document.getFile().getParentDirectory()));
384 layout.getSelectedSet().selectOnly (newOne);
387 layout.getDocument()->getUndoManager().beginNewTransaction();
392 ComponentOverlayComponent* ComponentLayoutEditor::getOverlayCompFor (Component* compToFind) const
394 for (int i = getNumChildComponents(); --i >= 0;)
396 ComponentOverlayComponent* const overlay = dynamic_cast <ComponentOverlayComponent*> (getChildComponent (i));
398 if (overlay != 0 && overlay->target == compToFind)
399 return overlay;
402 return 0;
405 void ComponentLayoutEditor::findLassoItemsInArea (Array <Component*>& results, const Rectangle<int>& area)
407 const Rectangle<int> lasso (area - subCompHolder->getPosition());
409 for (int i = 0; i < subCompHolder->getNumChildComponents(); ++i)
411 Component* c = subCompHolder->getChildComponent (i);
413 if (c->getBounds().intersects (lasso))
414 results.add (c);
418 SelectedItemSet <Component*>& ComponentLayoutEditor::getLassoSelection()
420 return layout.getSelectedSet();